import type { WidgetOptionSchema, ObjectSchema, ArraySchema } from '@learnware/wpe';

export function translateWidgetMeta(metaJson: any, metaType: string, translations: { [k: string]: any }) {
  const objectType = Object.prototype.toString.call(metaJson);
  if (objectType === '[object Object]') {
    Object.keys(metaJson).forEach(function(key) {
      metaJson[key] = translateWidgetMeta(metaJson[key], metaType, translations);
    });
    return metaJson
  }
  if (objectType === '[object Array]') {
    metaJson.forEach(function(item) {
      translateWidgetMeta(item, metaType, translations);
    });
    return metaJson;
  }
  if (objectType === '[object String]') {
    return localizeWidgetText(metaJson, metaType, translations);
  }
  return metaJson;
}

/**
 * 将控件配置文件中的某些字段替换成_locales文件夹下指定语言的翻译
 * 
 * 参数：
 *   text: 待翻译的字段，如 __MSG_displayName__
 *   metaType: 字段的来源，如来源于package.json则为package，来源于options.json则为options
 *   translations: JSON，目标语言的翻译，如解析后的_locales/zh-CN/package.json内的文件内容
 */
function localizeWidgetText(text: string, metaType: string, translations: { [k: string]: any }) {
  if (
    !text ||
    text.length < 9 ||
    !/^__MSG_/.test(text) ||
    !/__$/.test(text) ||
    !translations[metaType]
  ) return text;
  const keys = text.substring(6, text.length - 2).split('.');
  let localized = translations[metaType];
  for (let i = 0; i < keys.length; i++) {
    localized = localized[keys[i]];
    if (!localized) return text;
  }
  return localized;
}

export function updateWidgetPropValueByPropPath(
  widgetExtendedPropsData: { [k: string]: any },
  widgetExtendedPropsSchema: WidgetOptionSchema,
  propPath: Array<string | number>,
  value: any,
) {
  const [propName, ...deepProp] = propPath;

  let childData = widgetExtendedPropsData[propName];
  let childSchema = getChildSchema(widgetExtendedPropsSchema as (ObjectSchema | ArraySchema), propName);
  if (!childSchema) {
    console.error('Can NOT get schema of widget extended property');
    return;
  }
  if (typeof childData === 'undefined') {
    childData = widgetExtendedPropsData[propName] = getDefaultDataOfSchema(childSchema);
  }
  for (let i = 0; i < deepProp.length - 1; i++) {
    childSchema = getChildSchema(childSchema as (ObjectSchema | ArraySchema), deepProp[i]);
    if (!childSchema) {
      console.error('Can NOT get schema of widget extended property');
      return;
    }
    if (!childData[deepProp[i]]) {
      childData[deepProp[i]] = getDefaultDataOfSchema(childSchema);
    }
    childData = childData[deepProp[i]];
  }
  if (deepProp.length) {
    childData[deepProp[deepProp.length - 1]] = value;
  } else {
    widgetExtendedPropsData[propName] = value;
  }
}

export function getWidgetPropValueByPropPath(
  widgetExtendedPropsData: { [k: string]: any },
  widgetExtendedPropsSchema: WidgetOptionSchema,
  propPath: Array<string | number>,
) {
  const [propName, ...deepProp] = propPath;

  if (!deepProp.length) return widgetExtendedPropsData[propName];

  let childData = widgetExtendedPropsData[propName];
  let childSchema = getChildSchema(widgetExtendedPropsSchema as (ObjectSchema | ArraySchema), propName);
  if (!childSchema) {
    console.error('Can NOT get schema of widget extended property');
    return;
  }
  if (typeof childData === 'undefined') {
    childData = widgetExtendedPropsData[propName] = getDefaultDataOfSchema(childSchema);
  }
  for (let i = 0; i < deepProp.length - 1; i++) {
    childSchema = getChildSchema(childSchema as (ObjectSchema | ArraySchema), deepProp[i]);
    if (!childSchema) {
      console.error('Can NOT get schema of widget extended property');
      return;
    }
    if (!childData[deepProp[i]]) {
      childData[deepProp[i]] = getDefaultDataOfSchema(childSchema);
    }
    childData = childData[deepProp[i]];
  }
  return childData[deepProp[deepProp.length - 1]];
}

export function getChildSchema(parentSchema: ObjectSchema | ArraySchema, prop: string | number) {
  if (parentSchema.type === 'object') {
    return parentSchema.properties[prop];
  }
  return parentSchema.items;
}

export function getDefaultDataOfSchema(schema: WidgetOptionSchema) {
  let data: any;
  switch(schema.type) {
    case 'object':
      if (schema.default) {
        data = { ...schema.default };
      } else {
        data = {};
        Object.keys(schema.properties).forEach((propName) => {
          data[propName] = getDefaultDataOfSchema(schema.properties[propName]);
        });
      }
      break;
    case 'array':
      if (schema.default) {
        data = [ ...schema.default ];
      } else {
        data = [];
      }
      break;
    case 'string':
      data = schema.default || '';
      break;
    case 'number':
      data = schema.default || 0;
      break;
    case 'boolean':
      data = schema.default || false;
      break;
    default:
      break;
  }
  return data;
}